﻿using launcher.Common;
using launcher.Services;
using launcher.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Windows.Storage;
using Windows.Storage.Pickers;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace launcher.Views
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private MainPageViewModel ViewModel { get; }

        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
            this.Unloaded += MainPage_Unloaded;
            ViewModel = AppViewModel.Current.MainPageViewModel;
        }

        private static List<string> GetSuggestItems(IEnumerable<string> source, string text)
        {
            if (source == null || text == null)
            {
                return null;
            }

            var suitableItems = new List<string>();
            var splitText = text.ToLower().Split(" ");

            foreach (var item in source)
            {
                bool found = splitText.All((key) =>
                {
                    return item.ToLower().Contains(key);
                });
                if (found)
                {
                    suitableItems.Add(item);
                }
            }

            return suitableItems;
        }

        private string GetPlayButtonTooltip(bool paused)
        {
            var builder = new StringBuilder(paused ? "Resume" : "Pause").Append(" receiving text");
            var accelerator = playButton.KeyboardAccelerators.FirstOrDefault();
            if (accelerator != null)
            {
                builder.Append(" (")
                    .Append(Conversion.KeyboardAcceleratorToText(accelerator))
                    .Append(")");
            }
            return builder.ToString();
        }

        private string GetSuggestDocumentSaveName()
        {
            if (!string.IsNullOrWhiteSpace(ViewModel.ProcessName))
            {
                return ViewModel.ProcessName;
            }
            return "debug";
        }

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            pathSuggestBox.Text = ViewModel.ExecutableFilePath;
            filterSuggestBox.Text = ViewModel.TextFilter;
            regexSuggestBox.Text = ViewModel.RegexFilter;

            richTextBlock.FontFamily = new FontFamily(Settings.Defaults.TextFontFamilyName);
            richTextBlock.FontSize = Settings.Defaults.TextFontSize;
            richTextBlock.LineHeight = Settings.Defaults.TextLineHeight;

            ViewModel.TextParagraphs.CollectionChanged += TextParagraphs_CollectionChanged;
            ViewModel.ReloadDisplayedText();
        }

        private void MainPage_Unloaded(object sender, RoutedEventArgs e)
        {
            ViewModel.TextParagraphs.CollectionChanged -= TextParagraphs_CollectionChanged;
        }

        private async void launchButton_Click(object sender, SplitButtonClickEventArgs e)
        {
            ViewModel.ExecutableFilePath = pathSuggestBox.Text;
            ViewModel.TextFilter = filterSuggestBox.Text;
            ViewModel.RegexFilter = regexSuggestBox.Text;
            await ViewModel.Launch(ViewModel.ExecutableFilePath);
        }

        private void pathSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
            {
                sender.ItemsSource = GetSuggestItems(ViewModel.HistoryExecutableFiles, sender.Text);
            }
        }

        private void pathSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            ViewModel.ExecutableFilePath = args.QueryText;
        }

        private void filterSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
            {
                sender.ItemsSource = GetSuggestItems(ViewModel.HistoryTextFilters, sender.Text);
            }
        }

        private void filterSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            ViewModel.TextFilter = args.QueryText;
        }

        private void filterSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
        {
        }

        private void regexSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
            {
                sender.ItemsSource = GetSuggestItems(ViewModel.HistoryRegexFilters, sender.Text);
            }
        }

        private void regexSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            ViewModel.RegexFilter = args.QueryText;
        }

        private void richTextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (richTextBlock.ActualHeight > scrollViewer.ActualHeight)
            {
                scrollViewer.ScrollToVerticalOffset(richTextBlock.ActualHeight);
            }
        }

        private void TextParagraphs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (var item in e.NewItems)
                    {
                        richTextBlock.Blocks.Add(item as Paragraph);
                    }
                    break;

                case NotifyCollectionChangedAction.Reset:
                    richTextBlock.Blocks.Clear();
                    break;
            }
        }

        private async void saveButton_Click(object sender, RoutedEventArgs e)
        {
            FileSavePicker filePicker = new FileSavePicker();

            // Associate the HWND with the file picker
            // https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/desktop-to-uwp-supported-api?tabs=csharp#classes-that-use-iinitializewithwindow
            var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(AppViewModel.Current.MainWindow);
            WinRT.Interop.InitializeWithWindow.Initialize(filePicker, hwnd);

            filePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            filePicker.FileTypeChoices.Add("Log File", new List<string>() { ".log" });
            filePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
            filePicker.SuggestedFileName = GetSuggestDocumentSaveName();

            StorageFile file = await filePicker.PickSaveFileAsync();
            if (file != null)
            {
                await ViewModel.SaveDisplayedText(file);
            }
        }

        private void settingButton_Click(object sender, RoutedEventArgs e)
        {
            this.Frame.Navigate(typeof(SettingPage));
        }

        private async void findButton_Click(object sender, RoutedEventArgs e)
        {
            launchButton.Flyout.Hide();

            FileOpenPicker filePicker = new FileOpenPicker();

            // Associate the HWND with the file picker
            // https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/desktop-to-uwp-supported-api?tabs=csharp#classes-that-use-iinitializewithwindow
            var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(AppViewModel.Current.MainWindow);
            WinRT.Interop.InitializeWithWindow.Initialize(filePicker, hwnd);

            filePicker.FileTypeFilter.Add(".exe");

            StorageFile file = await filePicker.PickSingleFileAsync();
            if (file != null)
            {
                pathSuggestBox.Text = file.Path;
            }
        }
    }
}
